// C source file with the function definitions to handle BMD data

// check_j3dgraph_bmd() function
// function to check if a J3DGraph BMD is valid
j3dgraph_t check_j3dgraph_bmd(char * fpath)
{  
  // use open_j3dgraph_inc() to check the file (it is needed anyways)
  j3dgraph * file = open_j3dgraph_inc(fpath);
  if (file == NULL)
    goto err;
  // check the header and the sections of the BMD/BDL
  // starting array
  if (comp_bytes(file -> HEADER.ID, J3DGRAPH_BMD_ID[file -> ENDIAN - 1], 4) == false)
    goto err;  
  // check section count, considering the file type
  if (get_std_uint(32, file -> HEADER.SEC_CNT, file -> ENDIAN) != J3DGRAPH_BMD_SEC_CNT)
    goto err;
  
  // Unknown 1 does not have to be checked to be honest...
    
  // section checks
  bool check_result = true;
  check_result = check_result && check_j3dgraph_bmd_inf1(file);
  check_result = check_result && check_j3dgraph_bmd_vtx1(file);
  check_result = check_result && check_j3dgraph_bmd_evp1(file);
  check_result = check_result && check_j3dgraph_bmd_drw1(file);
  check_result = check_result && check_j3dgraph_bmd_jnt1(file);
  check_result = check_result && check_j3dgraph_bmd_shp1(file);
  check_result = check_result && check_j3dgraph_bmd_mat3(file);
  check_result = check_result && check_j3dgraph_bmd_tex1(file);  
  // best check of them all
  if (check_result == false)
    goto err;
  
  // all good
  close_j3dgraph_inc(file);
  return J3DGRAPH_BMD;
  
  // invalid section
  err:
  close_j3dgraph_inc(file);
  return J3DGRAPH_NO_TYPE;
}

// open_j3dgraph_bmd() function
// open a BMD (build a complete j3dgraph struct for BMD)
j3dgraph * open_j3dgraph_bmd(char * fpath)
{
  // check if the header/sections are valid
  j3dgraph * file = NULL;
  void * tmp[J3DGRAPH_BMD_SEC_CNT] = {NULL};
  // check if it is a BMD type
  if (check_j3dgraph_bmd(fpath) == J3DGRAPH_NO_TYPE)
    goto err;
  // open an incomplete j3dgraph struct and add the BMD sections to it
  file = open_j3dgraph_inc(fpath);
  file -> TYPE = J3DGRAPH_BMD;
  
  // build a complete j3dgraph BMD structure
  if ((tmp[J3DGRAPH_BMD_INF1_POS] = append_j3dgraph_bmd_inf1(file)) == NULL) goto err;
  if ((tmp[J3DGRAPH_BMD_VTX1_POS] = append_j3dgraph_bmd_vtx1(file)) == NULL) goto err;
  if ((tmp[J3DGRAPH_BMD_EVP1_POS] = append_j3dgraph_bmd_evp1(file)) == NULL) goto err;
  if ((tmp[J3DGRAPH_BMD_DRW1_POS] = append_j3dgraph_bmd_drw1(file)) == NULL) goto err;
  if ((tmp[J3DGRAPH_BMD_JNT1_POS] = append_j3dgraph_bmd_jnt1(file)) == NULL) goto err;
  if ((tmp[J3DGRAPH_BMD_SHP1_POS] = append_j3dgraph_bmd_shp1(file)) == NULL) goto err;
  if ((tmp[J3DGRAPH_BMD_MAT3_POS] = append_j3dgraph_bmd_mat3(file)) == NULL) goto err;
  if ((tmp[J3DGRAPH_BMD_TEX1_POS] = append_j3dgraph_bmd_tex1(file)) == NULL) goto err;
    
  // all went good
  return file;
  // failure
  err:
  for (umax i = 0; i < J3DGRAPH_BMD_SEC_CNT; i++)
    free_memory(tmp[i]);
  close_j3dgraph_inc(file);
  return NULL;
}

// close_j3dgraph_bmd() function
// function to close a complete j3dgraph BMD structure (free it)
void close_j3dgraph_bmd(j3dgraph * file)
{
  // free the memory allocated by all functions
  if (file == NULL || file -> TYPE != J3DGRAPH_BMD)
    return;
  
  // sections
  remove_j3dgraph_bmd_inf1(file);
  remove_j3dgraph_bmd_vtx1(file);
  remove_j3dgraph_bmd_evp1(file);
  remove_j3dgraph_bmd_drw1(file);
  remove_j3dgraph_bmd_jnt1(file);
  remove_j3dgraph_bmd_shp1(file);
  remove_j3dgraph_bmd_mat3(file);
  remove_j3dgraph_bmd_tex1(file);
  
  // j3dgraph structure
  close_j3dgraph_inc(file);
  
  // all done!
  return;
}

// print_j3dgraph_bmd() function
// print the information of a J3DGraph BMD
void print_j3dgraph_bmd(j3dgraph * file)
{
  // print everything header and sections
  // check ptr
  if (file == NULL)
    return;
  
  // starting visual queue
  printf("\n### J3DGraph BMD struct info start ###\n\n");
  
  // print the start of the j3dgraph struct
  print_j3dgraph_start(file);
  
  // section
  print_j3dgraph_bmd_inf1((j3dgraph_bmd_inf1 *) (file -> SEC)[J3DGRAPH_BMD_INF1_POS]);
  print_j3dgraph_bmd_vtx1((j3dgraph_bmd_vtx1 *) (file -> SEC)[J3DGRAPH_BMD_VTX1_POS]);
  print_j3dgraph_bmd_evp1((j3dgraph_bmd_evp1 *) (file -> SEC)[J3DGRAPH_BMD_EVP1_POS]);
  print_j3dgraph_bmd_drw1((j3dgraph_bmd_drw1 *) (file -> SEC)[J3DGRAPH_BMD_DRW1_POS]);
  print_j3dgraph_bmd_jnt1((j3dgraph_bmd_jnt1 *) (file -> SEC)[J3DGRAPH_BMD_JNT1_POS]);
  print_j3dgraph_bmd_shp1((j3dgraph_bmd_shp1 *) (file -> SEC)[J3DGRAPH_BMD_SHP1_POS]);
  print_j3dgraph_bmd_mat3((j3dgraph_bmd_mat3 *) (file -> SEC)[J3DGRAPH_BMD_MAT3_POS]);
  print_j3dgraph_bmd_tex1((j3dgraph_bmd_tex1 *) (file -> SEC)[J3DGRAPH_BMD_TEX1_POS]);
  
  // end of structure
  printf("\n### J3DGraph BMD struct info end ###\n");
  return;  
}
